﻿using System;

using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Grishko.DataTier.SqlLibrary
{

    /// <summary>
    ///базовый класс  описвающий параметр команды
    /// </summary>
    public class SqlStatment : EntitySingle
    {

        #region Разбор лексемы
        protected int LastEndPosition = 0;
        protected string CurrentSubstring = string.Empty;
        protected SqlWord CurrentWord = null;

      
         

        protected virtual List<SqlWord> GetWords()
        {             
            LastEndPosition = 0;
            CurrentSubstring = string.Empty;
            LastEndPosition = 0;
            _lexeme = _lexeme.Trim() + "#";

            List<SqlWord> res = new List<SqlWord>();
            // последняя позиция начала слова            

            for (int i = 0; i < _lexeme.Length + 1; i++)
            {
                // Формируем текущую подстроку  
                CurrentSubstring = _lexeme.Substring(LastEndPosition, i - LastEndPosition);

                //Если текущее слово изменилось - добавляем его в цепочку результатов                  
                bool bAddWord = false;
                bAddWord = SetNextWord(i);

                if (bAddWord)
                    res.Add(CurrentWord);


            }
            _lexeme = _lexeme.Replace("#", "");
            return res;
        }
        
        /// <summary>
        /// Фозвращает слова определнного типа 
        /// </summary>
        /// <param name="WordType"></param>
        /// <returns></returns>
        protected virtual List<SqlWord> GetWords(SqlWord.SqlWordType WordType)
        {
            var res =
            from n in GetWords()
            where n.WordType ==  WordType
            select n;

            return res.ToList<SqlWord>();
        }

        protected  virtual bool SetNextWord(int i)
        {
            // если пришел разделитель или конец строки   должны зафиксировать    CurrentWord
            if (CurrentSubstring.IndexOf(" ") > -1 || CurrentSubstring.IndexOf("#") > -1)
            {
                if (CurrentSubstringIsFunction)
                {
                    CurrentWord = new SqlFunc();
                }
                else
                {
                    CurrentWord = new Like();

                }


                LastEndPosition = i;
                CurrentWord.ParamString = CurrentSubstring.Replace("#", "");

                

                return true;
            }
            return false;



        }
        
        /// <summary>
        /// Флаг - является ли текущая подстрока функцией
        /// </summary>
        private bool CurrentSubstringIsFunction
        {
            get
            {
                foreach (SqlWord i in _FunctionWords)
                {
                    if (CurrentSubstring.ToUpper().IndexOf(i.ID.ToUpper()) > -1)
                        return true;
                }
                return false;
            }

        }
                
        private List<SqlWord> _FunctionWords = new List<SqlWord>();        
        /// <summary>
        /// Перечень функции - которые могут учавствовать в предложениии 
        /// </summary>        
        public virtual  List<SqlWord> FunctionWords 
        { 
            get { return _FunctionWords; }
        }
        #endregion


        #region Public
        private string _lexeme = string.Empty;
        /// <summary>
        /// Неразобраное предложение
        /// </summary>
        public string Lexeme
        {
            get { return _lexeme; }
            set{_lexeme = value;}
        }

        public SqlStatment() { }
        public SqlStatment(string Lexeme): base() 
        {
            _lexeme = Lexeme;
            
        }
        
        

        /// <summary>
        /// Сформировать SQL предложение. 
        /// </summary>
        /// <returns></returns>
        public virtual string GetStatment()
        {
            string res = "";
            List<SqlWord> rs = GetWords();  
            for (int i=0;i<rs.Count ;i++)
            {
                res=res+(i==0?"":" or ")+ rs[i].GetSql ();

            }            
            return res;
        }

        public virtual string GetStatment_Where(List<SqlWord> WordList)
        {
            string res = "";            
            for (int i = 0; i < WordList.Count; i++)
            {
                res = res + (i == 0 ? "" : " or ") + WordList[i].GetSql();

            }
            return res;
        }

        


        #endregion
        
    }    
}
